namespace My
{
    template<class T, class D = Delete<T>>
    class shared_ptr
    {
    public:
        shared_ptr(T* ptr = nullptr)
            :_ptr(ptr)
             ,_countptr(new int)
        {}

        shared_ptr(const shared_ptr<T, D>& sp)
            :_ptr(sp._ptr)
             ,_countptr(sp._countptr)
        {
            ++ (*_countptr);
        }

        shared_ptr<T, D>& operator=(const shared_ptr<T, D>& sp)
        {
            if (_ptr = sp._ptr)
                return *this;

            Release();

            _ptr = sp._ptr;
            _countptr = sp._countptr;
            ++ (*_countptr);

            return *this;
        }

        void Release()
        {
            if (--(*_countptr) == 0)
            {
                D()(_ptr);
                delete _countptr;
            }
        }

        ~shared_ptr() { Release(); }

        T& operator*() { return *_ptr; }
        T* operator->() { return _ptr; }

        T* get() const { return _ptr; }
        int use_count() { return *_countptr; }

    private:
        T* _ptr;
        int* _countptr;
    };
}
